package basic

import (
	"context"
	"fmt"
	"golang.org/x/sync/semaphore"
	"golang.org/x/sync/singleflight"
	"io"
	"net/http"
	"sync"
	"time"
)

func fetchURL(url string, sem *semaphore.Weighted) {
	// 获取一个许可
	sem.Acquire(context.Background(), 1)
	defer sem.Release(1)

	resp, err := http.Get(url)
	if err != nil {
		fmt.Printf("Failed to fetch %s: %v\n", url, err)
		return
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		fmt.Printf("Failed to read response from %s: %v\n", url, err)
		return
	}

	fmt.Printf("Fetched %s:\n%s\n", url, body)
}

func BasicSemaphore() {
	// 创建一个信号量，最多允许 3 个并发请求
	sem := semaphore.NewWeighted(3)

	// 定义要获取的 URL 列表
	urls := []string{
		"https://example.com",
		"https://example.org",
		"https://example.net",
		// 添加更多 URL
	}

	// 启动多个 goroutine 获取网页内容
	for _, url := range urls {
		go fetchURL(url, sem)
	}

	// 等待一段时间，确保所有 goroutine 完成
	time.Sleep(10 * time.Second)
}

// simulateExpensiveOperation 模拟一个耗时的操作
func simulateExpensiveOperation(key string) (string, error) {
	fmt.Printf("Starting expensive operation for key: %s\n", key)
	time.Sleep(2 * time.Second) // 模拟耗时操作
	fmt.Printf("Completed expensive operation for key: %s\n", key)
	return fmt.Sprintf("Result for key: %s", key), nil
}

func BasicSingleFlight() {
	// 创建 SingleFlight 实例
	sf := &singleflight.Group{}
	wg := sync.WaitGroup{}

	// 定义要处理的键列表
	keys := []string{"key1", "key1", "key2", "key2"}

	// 启动多个 goroutine 请求同一个操作
	for _, key := range keys {
		wg.Add(1)
		go func(key string) {
			defer wg.Done()
			// 使用 SingleFlight 确保同一操作只执行一次
			val, err, _ := sf.Do(key, func() (interface{}, error) {
				return simulateExpensiveOperation(key)
			})

			if err != nil {
				fmt.Printf("Error for key %s: %v\n", key, err)
			} else {
				fmt.Printf("Result for key %s: %s\n", key, val.(string))
			}
		}(key)
	}

	// 等待确保所有的goroutine都执行完毕
	wg.Wait()

	time.Sleep(5 * time.Second)

}
